#pragma once

#include <processUtil.h>
#include <fmt/format.h>
#include <json/json.h>
#include <string>
#include <system_error>
#include <sstream>
#include <fstream>
#include <vector>

namespace Tshark
{
    enum class error_code
    {
        success = 0,
        file_not_exits,
        file_open_failed,
        parse_error,
        out_of_range,
        popen_failed,
        failed,
        parse_pcap_failed
    };

    auto &tshark_error_category();

    /// @brief 创建Tshark::error_ec相关的错误码
    /// @param ec
    /// @return std::error_code
    std::error_code make_error_code(error_code ec);

    /// @brief 结果结构体，包含一个错误码和一个结果。
    ///     错误码用于指示结果是否有效，如果无效可以使用make_error_code(ec)返回std::error_code ec，使用 ec.category().message(ec.value) 可以得到错误信息。
    /// @tparam T Result中result的类型，即需要返回的结果的类型
    template <typename T>
    struct Result
    {
        T result;
        error_code ec;
        operator bool()
        {
            return ec == error_code::success;
        }
    };

    namespace DataType
    {
        enum class parse_erroc
        {
            success = 0,
            failed,
        };

        const char *protocolStrErr(parse_erroc ec);

        auto &protocolErrocCategory();

        std::error_code make_error_code(const parse_erroc &ec);

        struct ParseResult
        {
            parse_erroc code{parse_erroc::failed};
            std::string err_msg;

            operator bool()
            {
                return code == parse_erroc::success;
            }
        };

        /// @brief 读取文件指定偏移量offset的length个字符到buffer中
        /// @param PcapFile
        /// @param offset
        /// @param length
        /// @param buffer
        /// @return
        ParseResult readPacketHex(const std::string &PcapFile, uint32_t offset, uint16_t length, std::vector<unsigned char> &buffer);

        /// @brief pacp文件头部
        struct PcapHeader
        {
            // 顺序不能改变，否则memcpy会出问题
            uint32_t magic_number;  // 用于标识文件格式，典型值为0xa1b2c3d4（大端）或0xd4c3b2a1（小端）
            uint16_t version_major; // 主版本号
            uint16_t version_minor; // 次版本号
            uint32_t thiszone;      // 时区偏移，通常为0
            uint32_t sigfigs;       // 时间戳精度，通常为0
            uint32_t snaplen;       // 捕获的数据包最大长度
            uint32_t network;       // linktype，链路层类型，如以太网(0x01)
        };

        /// @brief packet数据包头部
        struct PacketHeader
        {
            // 顺序不能改变，否则memcpy会出问题
            uint32_t ts_sec;  // 时间戳，秒
            uint32_t ts_usec; // 时间戳，毫秒
            uint32_t caplen;  // 实际捕获数据包长度
            uint32_t len;     // 原始数据包长度
        };

        /// @brief 数据包内容
        struct Packet
        {
            int frame_number;         // 数据包编号
            double time;              // 数据包的时间戳
            std::string src_ip;       // 源IP地址
            std::string src_location; // 源ip归属地
            uint16_t src_port;        // 源端口
            std::string dst_ip;       // 目的IP地址
            std::string dst_location; // 源ip归属地
            uint16_t dst_port;        // 目的端口
            std::string protocol;     // 协议
            std::string info;         // 数据包的概要信息
            uint32_t cap_len;         // 包长度
            uint32_t len;
            std::string src_mac;  // 源mac地址
            std::string dst_mac;  // 目的mac地址
            uint32_t file_offset; // pcap中的文件偏移

            ParseResult parseLine(std::string line);

            std::string to_string() const;

            Json::Value to_json() const;
        };

        /// @brief 网卡信息
        struct AdapterInfo
        {
            AdapterInfo() = default;
            AdapterInfo(int id, const std::string &name, const std::string &remark)
                : id(id), name(name), remark(remark) {}

            std::string toString() const
            {
                return fmt::format("networkinterface id[{}] name[{}] remark[{}]\n", this->id, this->name.c_str(), this->remark);
            }

            Json::Value toJson() const
            {
                Json::Value adapterInfo;
                adapterInfo["id"] = id;
                adapterInfo["name"] = name;
                adapterInfo["remark"] = remark;
                return adapterInfo;
            }

            int id;
            std::string name;
            std::string remark;
        };

        /// @brief 网卡流量监控结构体
        struct AdapterMonitorInfo
        {
            AdapterMonitorInfo();

            std::string adapterName;                    // 网卡名称
            std::map<long, long> flowTrendData;         // 流量趋势数据,<时间戳,字节数>
            std::shared_ptr<std::thread> monitorThread; // 负责监视该网卡输出的线程
            FILE *monitorTsharkPipe{nullptr};           // 线程与tshark进程通信的管道
            PID_T tstarkPid;                            // 负责捕获该网卡数据的tshark进程PID
        };
    }
}